package utilities;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import net.knightwatch.kwtools.database.KwToolsDatasource;
import net.knightwatch.kwtools.walkthrough.Potential;
import net.knightwatch.kwtools.walkthrough.items.Answer;
import net.knightwatch.kwtools.walkthrough.items.BooleanAnswer;
import net.knightwatch.kwtools.walkthrough.items.Item;
import net.knightwatch.kwtools.walkthrough.items.PhotoAnswer;
import net.knightwatch.kwtools.walkthrough.items.Question;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfWriter;

/**
 * Generates a potential's PDF Document
 * 
 * @author nsteele
 */

public class PdfGenerator {
	private final static String TAG = "PdfGenerator";
	public final static String FOLDER_NAME = "kwtools";
	private static Font catFont = new Font(Font.TIMES_ROMAN, 18, Font.BOLD);
	//private static Font redFont = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.NORMAL, BaseColor.RED);
	private static Font standard = new Font(Font.TIMES_ROMAN, 12, Font.NORMAL);
	//private static Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.BOLD);
	private static Font smallBold = new Font(Font.TIMES_ROMAN, 12, Font.BOLD);
	/**
	 * Generates a filename of the PDF that was created on the SDCard
	 * @param potentialId
	 * @return
	 */
	public static Uri createPotentialPDF(long potentialId, Context context){
		// Set the local variables
		Document document = new Document();
		KwToolsDatasource database = new KwToolsDatasource(context);
		String fullPath = checkForFolder(FOLDER_NAME) + potentialId + ".pdf";
		Potential potential = new Potential();
		Uri uri;
		try{
			database.Open();
			potential = database.getPotential(potentialId);
			fullPath = checkForFolder(FOLDER_NAME) 
					+ database.getCustomer(potential.getCustomerId()).getCustomerName().replaceAll("\\W", "-") 
					+ "_" 
					+ potential.getName().replaceAll("\\W", "-") 
					+ "_"
					+potential.getId()
					+".pdf";
			Log.v(TAG, "New Full path is "+ fullPath);
		} catch (Exception e){
			e.printStackTrace();
		} finally{
			database.Close();
		}
		//create the potential report
		try{
			database.Open(); 
			PdfWriter.getInstance(document, new FileOutputStream(fullPath));
			document.open();
			// Add the meta data
			addMetaData(document);
			// Create the new paragraph for the header. 
			Paragraph potentialReport = new Paragraph();
		    // We add one empty line
		    addEmptyLine(potentialReport, 1);
		    // Big header with the name of the potential
		    potentialReport.add(new Paragraph("Name: " + potential.getName(), catFont));
		    potentialReport.add(new Paragraph("Create Date: " + potential.getCreateDate() , standard));
		    potentialReport.add(new Paragraph("Project Start Date: "+potential.getProjectedStartDate(), standard));
		    try {
				potentialReport.add(new Paragraph("Customer Name: " + database.getCustomer(potential.getCustomerId()).getCustomerName(), standard));
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				Log.w(TAG, "Unable to retrieve customer name for potential report");
				e1.printStackTrace();
			}
		    try {
				potentialReport.add(new Paragraph("Building: " + database.getBuilding(potential.getBuildingId()).getName(), standard));
				potentialReport.add(new Paragraph("Address:", standard));
				potentialReport.add(new Paragraph(database.getBuilding(potential.getBuildingId()).getAddress().getStreet(), standard));
				potentialReport.add(new Paragraph(database.getBuilding(potential.getBuildingId()).getAddress().getCity() 
						+ ", " 
						+ database.getBuilding(potential.getBuildingId()).getAddress().getState()
						+ " "
						+ database.getBuilding(potential.getBuildingId()).getAddress().getZipcode()
						, standard));
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				Log.w(TAG, "Unable to retireve building information for potential report.");
				e1.printStackTrace();
			}
		    potentialReport.add(new Paragraph("Overall Scope of Work:", catFont));
		    potentialReport.add(new Paragraph(potential.getScopeOfWork(), standard));
		    // Lookup the Items
		    potential.setItems(database.getPotentialItems(potentialId));
			// Get items questions and answers
			for(Item i : potential.getItems()){
				potentialReport.add(new Paragraph("type:" + i.getItemType().getName() + " id:" + i.getItemId() + " name:" + i.getName(), catFont));
				i.setQuestions(database.getItemQuestions(i.getItemType()));
				for(Question q : i.getQuestions()){
					try {
						Log.d(TAG, "Answer Type Id = " + q.getAnswer().getAnswerTypeId());
						switch(q.getAnswer().getAnswerTypeId()){
						case(Answer.PHOTO_TYPE):
							Log.d(TAG, "Create a photo on the PDF Document");
							PhotoAnswer photoAnswer = (PhotoAnswer) database.getAnswer(i.getItemId(), q.getQuestionId(), q.getAnswer().getAnswerTypeId());
							
							// Display the photo caption
							// Display the photo
							Log.d(TAG, "Photo Size " + photoAnswer.getPhoto().getByteCount());
							// Add the photo to the PDF
							byte[] imageData = bitmaptoByteArray(photoAnswer.getPhoto());
							Log.d(TAG, "ImageData Length = " + imageData.length);
							Image image = Image.getInstance(imageData);
							potentialReport.add(new Paragraph("Photo: "+q.getQuestion()));
							potentialReport.add(image);
							Log.d(TAG, "Add Photo Answer to PDF");
							break;
						case(Answer.BOOLEAN_TYPE):
							BooleanAnswer booleanAnswer = (BooleanAnswer) database.getAnswer(i.getItemId(), q.getQuestionId(), q.getAnswer().getAnswerTypeId());
							potentialReport.add(new Paragraph("Q:"+q.getQuestion()+" ==> A:" + booleanAnswer.getAnswer()));
							break;
						default:
							// Display the answers that are text
							q.setAnswer(database.getAnswer(i.getItemId(), q.getQuestionId(), q.getAnswer().getAnswerTypeId()));
							potentialReport.add(new Paragraph("Q:"+q.getQuestion()+" ==> A:" + database.getAnswer(i.getItemId(),  q.getQuestionId(),  q.getAnswer().getAnswerTypeId())));	
							break;
						}
					} catch (Exception e) {
						// TODO Auto-generated catch block
						Log.e(TAG, "Unable to setup the specific answer");
						e.printStackTrace();
					}
				}
			}
		    // Will create: Report generated by: _name, _date
		    // End of document
		    potentialReport.add(new Paragraph("End of Report generated at: " + new Date(), smallBold));
		    document.add(potentialReport);
		    Log.d(TAG, "File was saved to" + fullPath);
		} catch (DocumentException de){
			System.err.println(de.getMessage());
		} catch (IOException ioe) {
            System.err.println(ioe.getMessage());
		} finally {
			database.Close();
		}
        document.close();
        // returcn the path to the document
        uri = Uri.fromFile(new File(fullPath));
        return uri;
	}
	private static void addMetaData(Document document) {
	    document.addTitle("Potential Item Report");
	    document.addSubject("Sales Requirements");
	    document.addKeywords("PDF, Potential, Sales");
	    document.addAuthor("Knight Watch Inc.");
	    document.addCreator("kwtools android app");
	}
	private static void addEmptyLine(Paragraph paragraph, int number) {
		for (int i = 0; i < number; i++) {
	    	paragraph.add(new Paragraph(" "));
	    }
	}
	private static String checkForFolder(String folderName) {
		String fullPath = "";
		File folder = new File(android.os.Environment.getExternalStorageDirectory()
				+ java.io.File.separator
				+ folderName);
		boolean success = false;
		if (!folder.exists()) {
		    success = folder.mkdir();
		}
		if (!success) {
			fullPath = folder.getAbsolutePath() + java.io.File.separator;
			Log.d(TAG, "Directory on the SD Card has been created");
		    // Do something on success
		} else {
			Log.e(TAG, "Unable to create the directory");
		    // Do something else on failure 
		}
		
		return fullPath;
	}
	private static byte[] bitmaptoByteArray(Bitmap photo) {
		// Method to convert the photo to a byteArray.
		Log.d(TAG, "Converting bitmap size " + photo.getByteCount() +" to ByteArray");
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        photo.compress(Bitmap.CompressFormat.PNG, 100, stream);
        byte[] byteArray = stream.toByteArray();
        return byteArray;
	}
}
